home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / mozilla-firefox / include / string / nsCharTraits.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  18KB  |  785 lines

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 2000
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Scott Collins <scc@mozilla.org> (original author)
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  27.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. #ifndef nsCharTraits_h___
  40. #define nsCharTraits_h___
  41.  
  42. #include <ctype.h>
  43.   // for |EOF|, |WEOF|
  44.  
  45. #define FORCED_CPP_2BYTE_WCHAR_T
  46.   // disable special optimizations for now through this hack
  47.  
  48. #if defined(HAVE_CPP_2BYTE_WCHAR_T) && !defined(FORCED_CPP_2BYTE_WCHAR_T)
  49. #define USE_CPP_WCHAR_FUNCS
  50. #endif
  51.  
  52. #ifdef USE_CPP_WCHAR_FUNCS
  53. #include <wchar.h>
  54.   // for |wmemset|, et al
  55. #endif
  56.  
  57. #include <string.h>
  58.   // for |memcpy|, et al
  59.  
  60. #ifndef nscore_h___
  61. #include "nscore.h"
  62.   // for |PRUnichar|
  63. #endif
  64.  
  65. #ifndef nsDebug_h__
  66. #include "nsDebug.h"
  67.   // for NS_ASSERTION
  68. #endif
  69.  
  70. #ifdef HAVE_CPP_BOOL
  71.   typedef bool nsCharTraits_bool;
  72. #else
  73.   typedef PRBool nsCharTraits_bool;
  74. #endif
  75.  
  76. template <class CharT> struct nsCharTraits {};
  77.  
  78. NS_SPECIALIZE_TEMPLATE
  79. struct nsCharTraits<PRUnichar>
  80.   {
  81.     typedef PRUnichar char_type;
  82.     typedef PRUint16  unsigned_char_type;
  83.     typedef char      incompatible_char_type;
  84.  
  85.     NS_COM static const char_type *sEmptyBuffer;
  86.  
  87.     static
  88.     void
  89.     assign( char_type& lhs, char_type rhs )
  90.       {
  91.         lhs = rhs;
  92.       }
  93.  
  94.  
  95.       // integer representation of characters:
  96.  
  97. #ifdef USE_CPP_WCHAR_FUNCS
  98.     typedef wint_t int_type;
  99. #else
  100.     typedef int int_type;
  101. #endif
  102.  
  103.     static
  104.     char_type
  105.     to_char_type( int_type c )
  106.       {
  107.         return char_type(c);
  108.       }
  109.  
  110.     static
  111.     int_type
  112.     to_int_type( char_type c )
  113.       {
  114.         return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
  115.       }
  116.  
  117.     static
  118.     nsCharTraits_bool
  119.     eq_int_type( int_type lhs, int_type rhs )
  120.       {
  121.         return lhs == rhs;
  122.       }
  123.  
  124.  
  125.       // |char_type| comparisons:
  126.  
  127.     static
  128.     nsCharTraits_bool
  129.     eq( char_type lhs, char_type rhs )
  130.       {
  131.         return lhs == rhs;
  132.       }
  133.  
  134.     static
  135.     nsCharTraits_bool
  136.     lt( char_type lhs, char_type rhs )
  137.       {
  138.         return lhs < rhs;
  139.       }
  140.  
  141.  
  142.       // operations on s[n] arrays:
  143.  
  144.     static
  145.     char_type*
  146.     move( char_type* s1, const char_type* s2, size_t n )
  147.       {
  148.         return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
  149.       }
  150.  
  151.     static
  152.     char_type*
  153.     copy( char_type* s1, const char_type* s2, size_t n )
  154.       {
  155.         return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
  156.       }
  157.  
  158.     static
  159.     char_type*
  160.     copyASCII( char_type* s1, const char* s2, size_t n )
  161.       {
  162.         for (char_type* s = s1; n--; ++s, ++s2) {
  163.           NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  164.           *s = *s2;
  165.         }
  166.         return s1;
  167.       }
  168.  
  169.     static
  170.     char_type*
  171.     assign( char_type* s, size_t n, char_type c )
  172.       {
  173. #ifdef USE_CPP_WCHAR_FUNCS
  174.         return NS_STATIC_CAST(char_type*, wmemset(s, to_int_type(c), n));
  175. #else
  176.         char_type* result = s;
  177.         while ( n-- )
  178.           assign(*s++, c);
  179.         return result;
  180. #endif
  181.       }
  182.  
  183.     static
  184.     int
  185.     compare( const char_type* s1, const char_type* s2, size_t n )
  186.       {
  187. #ifdef USE_CPP_WCHAR_FUNCS
  188.         return wmemcmp(s1, s2, n);
  189. #else
  190.         for ( ; n--; ++s1, ++s2 )
  191.           {
  192.             if ( !eq(*s1, *s2) )
  193.               return to_int_type(*s1) - to_int_type(*s2);
  194.           }
  195.  
  196.         return 0;
  197. #endif
  198.       }
  199.  
  200.     static
  201.     int
  202.     compareASCII( const char_type* s1, const char* s2, size_t n )
  203.       {
  204.         for ( ; n--; ++s1, ++s2 )
  205.           {
  206.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  207.             if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
  208.               return to_int_type(*s1) - to_int_type(*s2);
  209.           }
  210.  
  211.         return 0;
  212.       }
  213.  
  214.     // this version assumes that s2 is null-terminated and s1 has length n.
  215.     // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
  216.     // we return 1.
  217.     static
  218.     int
  219.     compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
  220.       {
  221.         for ( ; n--; ++s1, ++s2 )
  222.           {
  223.             if ( !*s2 )
  224.               return 1;
  225.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  226.             if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
  227.               return to_int_type(*s1) - to_int_type(*s2);
  228.           }
  229.  
  230.         if ( *s2 )
  231.           return -1;
  232.  
  233.         return 0;
  234.       }
  235.  
  236.     /**
  237.      * Convert c to its lower-case form, but only if the lower-case form is
  238.      * ASCII. Otherwise leave it alone.
  239.      *
  240.      * There are only two non-ASCII Unicode characters whose lowercase
  241.      * equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH
  242.      * DOT ABOVE. So it's a simple matter to handle those explicitly.
  243.      */
  244.     static
  245.     char_type
  246.     ASCIIToLower( char_type c )
  247.       {
  248.         if (c < 0x100)
  249.           return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
  250.         else
  251.           {
  252.             if (c == 0x212A) // KELVIN SIGN
  253.               return 'k';
  254.             if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE
  255.               return 'i';
  256.             return c;
  257.           }
  258.       }
  259.  
  260.     static
  261.     int
  262.     compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
  263.       {
  264.         for ( ; n--; ++s1, ++s2 )
  265.           {
  266.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  267.             NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
  268.                          "Unexpected uppercase character");
  269.             char_type lower_s1 = ASCIIToLower(*s1);
  270.             if ( lower_s1 != to_char_type(*s2) )
  271.               return to_int_type(lower_s1) - to_int_type(*s2);
  272.           }
  273.  
  274.         return 0;
  275.       }
  276.  
  277.     // this version assumes that s2 is null-terminated and s1 has length n.
  278.     // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
  279.     // we return 1.
  280.     static
  281.     int
  282.     compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
  283.       {
  284.         for ( ; n--; ++s1, ++s2 )
  285.           {
  286.             if ( !*s2 )
  287.               return 1;
  288.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  289.             NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
  290.                          "Unexpected uppercase character");
  291.             char_type lower_s1 = ASCIIToLower(*s1);
  292.             if ( lower_s1 != to_char_type(*s2) )
  293.               return to_int_type(lower_s1) - to_int_type(*s2);
  294.           }
  295.  
  296.         if ( *s2 )
  297.           return -1;
  298.  
  299.         return 0;
  300.       }
  301.  
  302.     static
  303.     size_t
  304.     length( const char_type* s )
  305.       {
  306. #ifdef USE_CPP_WCHAR_FUNCS
  307.         return wcslen(s);
  308. #else
  309.         size_t result = 0;
  310.         while ( !eq(*s++, char_type(0)) )
  311.           ++result;
  312.         return result;
  313. #endif
  314.       }
  315.  
  316.     static
  317.     const char_type*
  318.     find( const char_type* s, size_t n, char_type c )
  319.       {
  320. #ifdef USE_CPP_WCHAR_FUNCS
  321.         return NS_REINTERPRET_CAST(const char_type*, wmemchr(s, to_int_type(c), n));
  322. #else
  323.         while ( n-- )
  324.           {
  325.             if ( eq(*s, c) )
  326.               return s;
  327.             ++s;
  328.           }
  329.  
  330.         return 0;
  331. #endif
  332.       }
  333.  
  334. #if 0
  335.       // I/O related:
  336.  
  337.     typedef streamoff off_type;
  338.     typedef streampos pos_type;
  339.     typedef mbstate_t state_type;
  340.  
  341.     static
  342.     int_type
  343.     eof()
  344.       {
  345. #ifdef USE_CPP_WCHAR_FUNCS
  346.         return WEOF;
  347. #else
  348.         return EOF;
  349. #endif
  350.       }
  351.  
  352.     static
  353.     int_type
  354.     not_eof( int_type c )
  355.       {
  356.         return eq_int_type(c, eof()) ? ~eof() : c;
  357.       }
  358.  
  359.     // static state_type get_state( pos_type );
  360. #endif
  361.   };
  362.  
  363. NS_SPECIALIZE_TEMPLATE
  364. struct nsCharTraits<char>
  365.   {
  366.     typedef char           char_type;
  367.     typedef unsigned char  unsigned_char_type;
  368.     typedef PRUnichar      incompatible_char_type;
  369.  
  370.     NS_COM static const char_type *sEmptyBuffer;
  371.  
  372.     static
  373.     void
  374.     assign( char_type& lhs, char_type rhs )
  375.       {
  376.         lhs = rhs;
  377.       }
  378.  
  379.  
  380.       // integer representation of characters:
  381.  
  382.     typedef int int_type;
  383.  
  384.     static
  385.     char_type
  386.     to_char_type( int_type c )
  387.       {
  388.         return char_type(c);
  389.       }
  390.  
  391.     static
  392.     int_type
  393.     to_int_type( char_type c )
  394.       {
  395.         return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
  396.       }
  397.  
  398.     static
  399.     nsCharTraits_bool
  400.     eq_int_type( int_type lhs, int_type rhs )
  401.       {
  402.         return lhs == rhs;
  403.       }
  404.  
  405.  
  406.       // |char_type| comparisons:
  407.  
  408.     static
  409.     nsCharTraits_bool
  410.     eq( char_type lhs, char_type rhs )
  411.       {
  412.         return lhs == rhs;
  413.       }
  414.  
  415.     static
  416.     nsCharTraits_bool
  417.     lt( char_type lhs, char_type rhs )
  418.       {
  419.         return lhs < rhs;
  420.       }
  421.  
  422.  
  423.       // operations on s[n] arrays:
  424.  
  425.     static
  426.     char_type*
  427.     move( char_type* s1, const char_type* s2, size_t n )
  428.       {
  429.         return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
  430.       }
  431.  
  432.     static
  433.     char_type*
  434.     copy( char_type* s1, const char_type* s2, size_t n )
  435.       {
  436.         return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
  437.       }
  438.  
  439.     static
  440.     char_type*
  441.     copyASCII( char_type* s1, const char* s2, size_t n )
  442.       {
  443.         return copy(s1, s2, n);
  444.       }
  445.  
  446.     static
  447.     char_type*
  448.     assign( char_type* s, size_t n, char_type c )
  449.       {
  450.         return NS_STATIC_CAST(char_type*, memset(s, to_int_type(c), n));
  451.       }
  452.  
  453.     static
  454.     int
  455.     compare( const char_type* s1, const char_type* s2, size_t n )
  456.       {
  457.         return memcmp(s1, s2, n);
  458.       }
  459.  
  460.     static
  461.     int
  462.     compareASCII( const char_type* s1, const char* s2, size_t n )
  463.       {
  464. #ifdef DEBUG
  465.         for (size_t i = 0; i < n; ++i)
  466.           {
  467.             NS_ASSERTION(!(s2[i] & ~0x7F), "Unexpected non-ASCII character");
  468.           }
  469. #endif
  470.         return compare(s1, s2, n);
  471.       }
  472.  
  473.     // this version assumes that s2 is null-terminated and s1 has length n.
  474.     // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
  475.     // we return 1.
  476.     static
  477.     int
  478.     compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
  479.       {
  480.         // can't use strcmp here because we don't want to stop when s1
  481.         // contains a null
  482.         for ( ; n--; ++s1, ++s2 )
  483.           {
  484.             if ( !*s2 )
  485.               return 1;
  486.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  487.             if ( *s1 != *s2 )
  488.               return to_int_type(*s1) - to_int_type(*s2);
  489.           }
  490.  
  491.         if ( *s2 )
  492.           return -1;
  493.  
  494.         return 0;
  495.       }
  496.  
  497.     /**
  498.      * Convert c to its lower-case form, but only if c is ASCII.
  499.      */
  500.     static
  501.     char_type
  502.     ASCIIToLower( char_type c )
  503.       {
  504.         return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
  505.       }
  506.  
  507.     static
  508.     int
  509.     compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
  510.       {
  511.         for ( ; n--; ++s1, ++s2 )
  512.           {
  513.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  514.             NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
  515.                          "Unexpected uppercase character");
  516.             char_type lower_s1 = ASCIIToLower(*s1);
  517.             if ( lower_s1 != *s2 )
  518.               return to_int_type(lower_s1) - to_int_type(*s2);
  519.           }
  520.         return 0;
  521.       }
  522.  
  523.     // this version assumes that s2 is null-terminated and s1 has length n.
  524.     // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
  525.     // we return 1.
  526.     static
  527.     int
  528.     compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
  529.       {
  530.         for ( ; n--; ++s1, ++s2 )
  531.           {
  532.             if ( !*s2 )
  533.               return 1;
  534.             NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
  535.             NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
  536.                          "Unexpected uppercase character");
  537.             char_type lower_s1 = ASCIIToLower(*s1);
  538.             if ( lower_s1 != *s2 )
  539.               return to_int_type(lower_s1) - to_int_type(*s2);
  540.           }
  541.  
  542.         if ( *s2 )
  543.           return -1;
  544.  
  545.         return 0;
  546.       }
  547.  
  548.     static
  549.     size_t
  550.     length( const char_type* s )
  551.       {
  552.         return strlen(s);
  553.       }
  554.  
  555.     static
  556.     const char_type*
  557.     find( const char_type* s, size_t n, char_type c )
  558.       {
  559.         return NS_REINTERPRET_CAST(const char_type*, memchr(s, to_int_type(c), n));
  560.       }
  561.  
  562. #if 0
  563.       // I/O related:
  564.  
  565.     typedef streamoff off_type;
  566.     typedef streampos pos_type;
  567.     typedef mbstate_t state_type;
  568.  
  569.     static
  570.     int_type
  571.     eof()
  572.       {
  573.         return EOF;
  574.       }
  575.  
  576.     static
  577.     int_type
  578.     not_eof( int_type c )
  579.       {
  580.         return eq_int_type(c, eof()) ? ~eof() : c;
  581.       }
  582.  
  583.     // static state_type get_state( pos_type );
  584. #endif
  585.   };
  586.  
  587. template <class InputIterator>
  588. struct nsCharSourceTraits
  589.   {
  590.     typedef typename InputIterator::difference_type difference_type;
  591.  
  592.     static
  593.     PRUint32
  594.     readable_distance( const InputIterator& first, const InputIterator& last )
  595.       {
  596.         // assumes single fragment
  597.         return last.get() - first.get();
  598.       }
  599.  
  600.     static
  601.     const typename InputIterator::value_type*
  602.     read( const InputIterator& iter )
  603.       {
  604.         return iter.get();
  605.       }
  606.  
  607.     static
  608.     void
  609.     advance( InputIterator& s, difference_type n )
  610.       {
  611.         s.advance(n);
  612.       }
  613.   };
  614.  
  615. #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
  616.  
  617. template <class CharT>
  618. struct nsCharSourceTraits<CharT*>
  619.   {
  620.     typedef ptrdiff_t difference_type;
  621.  
  622.     static
  623.     PRUint32
  624.     readable_distance( CharT* s )
  625.       {
  626.         return PRUint32(nsCharTraits<CharT>::length(s));
  627. //      return numeric_limits<PRUint32>::max();
  628.       }
  629.  
  630.     static
  631.     PRUint32
  632.     readable_distance( CharT* first, CharT* last )
  633.       {
  634.         return PRUint32(last-first);
  635.       }
  636.  
  637.     static
  638.     const CharT*
  639.     read( CharT* s )
  640.       {
  641.         return s;
  642.       }
  643.  
  644.     static
  645.     void
  646.     advance( CharT*& s, difference_type n )
  647.       {
  648.         s += n;
  649.       }
  650.   };
  651.  
  652. #else
  653.  
  654. NS_SPECIALIZE_TEMPLATE
  655. struct nsCharSourceTraits<const char*>
  656.   {
  657.     typedef ptrdiff_t difference_type;
  658.  
  659.     static
  660.     PRUint32
  661.     readable_distance( const char* s )
  662.       {
  663.         return PRUint32(nsCharTraits<char>::length(s));
  664. //      return numeric_limits<PRUint32>::max();
  665.       }
  666.  
  667.     static
  668.     PRUint32
  669.     readable_distance( const char* first, const char* last )
  670.       {
  671.         return PRUint32(last-first);
  672.       }
  673.  
  674.     static
  675.     const char*
  676.     read( const char* s )
  677.       {
  678.         return s;
  679.       }
  680.  
  681.     static
  682.     void
  683.     advance( const char*& s, difference_type n )
  684.       {
  685.         s += n;
  686.       }
  687.  };
  688.  
  689.  
  690. NS_SPECIALIZE_TEMPLATE
  691. struct nsCharSourceTraits<const PRUnichar*>
  692.   {
  693.     typedef ptrdiff_t difference_type;
  694.  
  695.     static
  696.     PRUint32
  697.     readable_distance( const PRUnichar* s )
  698.       {
  699.         return PRUint32(nsCharTraits<PRUnichar>::length(s));
  700. //      return numeric_limits<PRUint32>::max();
  701.       }
  702.  
  703.     static
  704.     PRUint32
  705.     readable_distance( const PRUnichar* first, const PRUnichar* last )
  706.       {
  707.         return PRUint32(last-first);
  708.       }
  709.  
  710.     static
  711.     const PRUnichar*
  712.     read( const PRUnichar* s )
  713.       {
  714.         return s;
  715.       }
  716.  
  717.     static
  718.     void
  719.     advance( const PRUnichar*& s, difference_type n )
  720.       {
  721.         s += n;
  722.       }
  723.  };
  724.  
  725. #endif
  726.  
  727.  
  728. template <class OutputIterator>
  729. struct nsCharSinkTraits
  730.   {
  731.     static
  732.     PRUint32
  733.     write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
  734.       {
  735.         return iter.write(s, n);
  736.       }
  737.   };
  738.  
  739. #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
  740.  
  741. template <class CharT>
  742. struct nsCharSinkTraits<CharT*>
  743.   {
  744.     static
  745.     PRUint32
  746.     write( CharT*& iter, const CharT* s, PRUint32 n )
  747.       {
  748.         nsCharTraits<CharT>::move(iter, s, n);
  749.         iter += n;
  750.         return n;
  751.       }
  752.   };
  753.  
  754. #else
  755.  
  756. NS_SPECIALIZE_TEMPLATE
  757. struct nsCharSinkTraits<char*>
  758.   {
  759.     static
  760.     PRUint32
  761.     write( char*& iter, const char* s, PRUint32 n )
  762.       {
  763.         nsCharTraits<char>::move(iter, s, n);
  764.         iter += n;
  765.         return n;
  766.       }
  767.   };
  768.  
  769. NS_SPECIALIZE_TEMPLATE
  770. struct nsCharSinkTraits<PRUnichar*>
  771.   {
  772.     static
  773.     PRUint32
  774.     write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
  775.       {
  776.         nsCharTraits<PRUnichar>::move(iter, s, n);
  777.         iter += n;
  778.         return n;
  779.       }
  780.   };
  781.  
  782. #endif
  783.  
  784. #endif // !defined(nsCharTraits_h___)
  785.